﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AIRO.Devices.PositioningDevice;
using AIRO.Devices.Ccd;
using Ivi.ConfigServer.Interop;
using Ivi.SessionFactory.Interop;
using System.Globalization;

namespace AIRO.NoiseCorr
{
    public partial class FrmMain : Form
    {

        /// <summary>
        /// The serial state
        /// </summary>
        public enum StateType
        {
            /// <summary>
            /// Application is idle.
            /// </summary>
            Idle,
            /// <summary>
            /// Serial is running.
            /// </summary>
            Running,
            /// <summary>
            /// Serial was cancelled by user request or error occured.
            /// </summary>
            Cancelled,
            /// <summary>
            /// The program will now exit.
            /// </summary>
            Exit
        }

        private double[] firstPointArr;
        private double[] secondPointArr;
        private int spectraCount;
        private int bCount;
        private double startField;
        private double afterField;
        private double curentField;
        private double stepField;
        private IPositioningDevice positioningDevice;
        private string positioningDeviceLogicalName;
        private ICcd ccd;
        private string ccdLogicalName;
        IviConfigStore configStore;
        private IIviSessionFactory sessionFactory = new IviSessionFactoryClass();
        protected NumberFormatInfo numericFormatProvider = new NumberFormatInfo();
        StateType _state;

        


        public FrmMain()
        {
            InitializeComponent();
        }

        /// <summary>The State property represents the serial state.</summary>
        /// <value>The State property gets/sets the _state data member.</value>
        public StateType State
        {
            get
            {
                return _state;
            }
            set
            {
                if (value == StateType.Running)
                {
                    //btExit.Enabled = false;
                    cbSolenoid.Enabled = false;
                    tbDesiredField.Enabled = false;
                    rbISolenoid.Enabled = false;
                    btSetStop.Text = "Cancel";
                    if (!isISolenoidActiveInterface)
                    {
                        btSetStop.Enabled = false;
                    }
                }
                else
                {
                    //btExit.Enabled = true;
                    cbSolenoid.Enabled = true;
                    tbDesiredField.Enabled = true;
                    rbISolenoid.Enabled = true;
                    btSetStop.Text = "Move";
                    btSetStop.Enabled = true;
                }
                _state = value;
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            readParams();
            startMeasure();
            calculateCorr();
            
        }

        private void calculateCorr()
        {

            correlation.spearmanrankcorrelation(firstPointArr, secondPointArr, spectraCount);
        }

        private void readParams()
        {
            startField = Convert.ToDouble(tbStartField.Text);
            stepField = Convert.ToDouble(tbStep.Text);
            bCount = Convert.ToInt32(tbCount.Text);
            afterField = Convert.ToDouble(tbFieldAfter.Text);
            tbFinalField.Text = Convert.ToString(startField + bCount * stepField);
            spectraCount = Convert.ToInt32(tbSpectraCount.Text);

            ccdLogicalName = cbCcd.Text;
            positioningDeviceLogicalName = cbSolenoid.Text;
            try
            {
                positioningDevice = (IPositioningDevice)sessionFactory.CreateDriver(positioningDeviceLogicalName);
                ((Ivi.Driver.Interop.IIviDriver)positioningDevice).Initialize(positioningDeviceLogicalName, false, false, "");
                //positioningDevice.StateChangedEvent += new EventHandler<AIRO.Devices.Solenoid.StateChangedEventArgs>(solenoid_StateChangedEvent);
                //positioningDevice.ProgressEvent += new EventHandler<AIRO.Devices.Solenoid.ProgressEventArgs>(solenoid_ProgressEvent);
                //positioningDevice.FieldSetEvent += new EventHandler<AIRO.Devices.Solenoid.FieldSetEventArgs>(solenoid_FieldSetEvent);
                updatePositioningDeviceState(positioningDevice.State);                
            }
            catch (Exception e)
            {
                this.Text = cbSolenoid.Text + " [Error]";
                MessageBox.Show(e.Message, "Can not initialize driver!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                btSetStop.Enabled = false;
                return;
            }
            btSetStop.Enabled = true;
            
        }

        private void updatePositioningDeviceState(PositioningDeviceState currentState)
        {
            switch (currentState)
            {
                case PositioningDeviceState.Idle:
                    State = StateType.Idle;
                    //btSetStop.Enabled = true;
                    //btExit.Enabled = true;
                    pbFieldStatus.Image = Properties.Resources.green_circle;
                    this.Text = cbSolenoid.Text + " [Idle]";
                    break;
                case PositioningDeviceState.Running:
                    //btSetStop.Enabled = false;
                    //btExit.Enabled = false;
                    pbFieldStatus.Image = Properties.Resources.yellow_circle;
                    this.Text = cbSolenoid.Text + " [Running]";
                    break;
                case PositioningDeviceState.Error:
                    //btSetStop.Enabled = false;
                    //btExit.Enabled = true;
                    switch (_state)
                    {
                        case StateType.Running:
                            State = StateType.Cancelled;
                            break;
                        default:
                            break;
                    }
                    pbFieldStatus.Image = Properties.Resources.red_circle;
                    this.Text = cbSolenoid.Text + " [Error]";
                    break;
            }
            
                tbCurrentField.Text = positioningDevice.Position.ToString();
            
        }


        private void startMeasure()    
        {
            ccd.NumberOfSpectra = spectraCount;
            for (int i = 0; i < bCount; i++)
            {
                curentField = startField + i * stepField;
                positioningDevice.Move(curentField);
                ccd.Measure();
                for (int j = 0; j < spectraCount; j++)
                {
                    ccd.GetFrame(j);
                }

            }
            if (cbAfterField.Checked)
                positioningDevice.Move(afterField);
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            configStore = new IviConfigStoreClass();
            string location;
            if (configStore.ProcessDefaultLocation != "")
            {
                location = configStore.ProcessDefaultLocation;
            }
            else if (configStore.MasterLocation != "")
            {
                location = configStore.MasterLocation;
            }
            else
            {
                throw new Exception("Process Default Location and Master Location are null strings!");
            }
            configStore.Deserialize(location);

            #region Search for CCDs and Positioning devices
            //cbSolenoid.Items.Clear();
            //string defaultDevice;
            foreach (IviLogicalName logicalName in configStore.LogicalNames)
            {
                IviSoftwareModule softwareModule = logicalName.Session.SoftwareModule;
                if (softwareModule != null)
                {
                    IviPublishedAPICollection publishedAPIs = softwareModule.PublishedAPIs;
                    string progID = softwareModule.ProgID;
                    Type type = Type.GetTypeFromProgID(progID);
                    if (type != null)
                    {
                        if (type.IsSubclassOf(typeof(IPositioningDevice)))
                        {
                            cbSolenoid.Items.Add(logicalName.Name);
                        }
                        else if (type.IsSubclassOf(typeof(ICcd)))
                        {
                            cbCcd.Items.Add(logicalName.Name);
                        }

                        //foreach (Type tInterface in type.GetInterfaces())
                        //{
                        //    // Является ли этот интерфейс ISolenoid или IPositioningDevice, т.е. тем что мы ищем
                        //    if (tInterface == typeof(IPositioningDevice))
                        //    {
                        //        //Если да, то добавляем logicalName в список опций
                        //        cbSolenoid.Items.Add(logicalName.Name);
                        //        /*
                        //        if (logicalName.Name == defaultDevice)
                        //            cbSolenoid.SelectedItem = defaultDevice;
                        //         * */
                        //    }
                        //}

                    }
                }
            }
            #endregion            
        }
    }
}
